package com.qingyun.video.utils;

import com.qingyun.common.exception.ServiceException;
import com.qingyun.common.utils.file.MimeTypeUtils;
import com.qingyun.video.config.FFmpegConfig;
import com.qingyun.video.ffmpeg.Encoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Slf4j
public class ConverVideoUtils {

    public ConverVideoUtils() {
    }

	public static void main(String[] args) {

		//beginConver("F:\\ffmpeg\\temp\\12345.mp4","F:\\ffmpeg\\temp\\123456.mp4",false);
	}
    /**
     * 转换视频格式
     * @param
     * @param isDelSourseFile 转换完成后是否删除源文件
     * @return
     */
    public static boolean beginConver(String sourceVideoPath,String outpath,String rate, boolean isDelSourseFile) {
        File fi = new File(sourceVideoPath);

       String  filename = fi.getName();//获取文件名+后缀名

      String filerealname = filename.substring(0, filename.lastIndexOf(".")); //获取不带后缀的文件名-后面加.toLowerCase()小写

        System.out.println("----接收到文件("+sourceVideoPath+")需要转换-------");

        //检测本地是否存在
		/*if (checkfile(sourceVideoPath)) {
			System.out.println(sourceVideoPath + "========该文件存在哟 ");
			return false;
		}*/

        System.out.println("----开始转文件(" + sourceVideoPath + ")-------------------------- ");

        //执行转码机制
        if (process(sourceVideoPath,outpath,rate)) {

            System.out.println("视频转码结束================= ");


            //删除原视频+临时视频
			if (isDelSourseFile) {
				File file1 = new File(sourceVideoPath);
				if (file1.exists()){
					System.out.println("删除原文件-可用："+sourceVideoPath);
					file1.delete();
				}
			}


            String temppath= FFmpegConfig.getTempAbsolutePath() + filerealname + ".avi";
//			String temppath= "F:\\ffmpeg\\temp\\" + filerealname + ".avi";

            File file2 = new File(temppath);
            if (file2.exists()){
                System.out.println("删除临时文件："+temppath);
                file2.delete();
            }

            sourceVideoPath = null;
            return true;
        } else {
            sourceVideoPath = null;
            return false;
        }
    }


    /**
     * 检查文件是否存在-多处都有判断
     * @param path
     * @return
     */

	/*private boolean checkfile(String path) {
		path = sourceVideoPath;
		File file = new File(path);
		try {
			if (file.exists()) {
				System.out.println("视频文件不存在============="+path);
				return true;
			} else {
				System.out.println("视频文件存在"+path);
				return false;
			}
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("拒绝对文件进行读访问");
		}
		return false;
	}*/

    /**
     * 实际转换视频格式的方法

     * @return
     */
    private static boolean process(String sourceVideoPath,String outPath,String rate) {

        //先判断视频的类型-返回状态码
        int type = checkContentType(sourceVideoPath);
        boolean status = false;

        //根据状态码处理
        if (type == 0) {
            System.out.println("ffmpeg可以转换,统一转为mp4文件");

            status = processVideoFormat(sourceVideoPath,outPath,rate);//可以指定转换为什么格式的视频

        } else if (type == 9) {
        	throw new ServiceException("转换格式不存在");
        }
        return status;   //执行完成返回布尔类型true
    }

    /**
     * 检查文件类型
     * @return
     */
    private static int checkContentType(String sourceVideoPath) {

        //取得视频后缀-
        String type = sourceVideoPath.substring(sourceVideoPath.lastIndexOf(".") + 1, sourceVideoPath.length()).toLowerCase();
        System.out.println("源视频类型为:"+type);

        // 如果是ffmpeg能解析的格式:(asx，asf，mpg，wmv，3gp，mp4，mov，avi，flv等)
        if (type.equals("avi")) {
            return 0;
        } else if (type.equals("mpg")) {
            return 0;
        } else if (type.equals("wmv")) {
            return 0;
        } else if (type.equals("3gp")) {
            return 0;
        } else if (type.equals("mov")) {
            return 0;
        } else if (type.equals("mp4")) {
            return 0;
        } else if (type.equals("asf")) {
            return 0;
        } else if (type.equals("asx")) {
            return 0;
        } else if (type.equals("flv")) {
            return 0;
        }else if (type.equals("mkv")) {
            return 0;
        }

        System.out.println("上传视频格式异常");
        return 9;
    }


    /**
     * 转换为指定格式--zoutao
     * ffmpeg能解析的格式：（asx，asf，mpg，wmv，3gp，mp4，mov，avi，flv等）
     * @param oldfilepath
     * @return
     */
    private static boolean processVideoFormat(String oldfilepath, String outPath,String rate) {

        System.out.println("调用了ffmpeg.exe工具");

		File file = new File(outPath);
		if (file.isFile()) {
			file.delete();
		}

		List<String> commend = new ArrayList<String>();
		Encoder encoder = new Encoder();
		commend.add(encoder.getLocator()); //ffmpeg.exe工具地址
//		commend.add("F:\\ffmpeg\\temp\\conf\\ffmpeg.exe");
        commend.add("-i");
        commend.add(oldfilepath);			//源视频路径

        commend.add("-vf");             //视频分辨率处理
		Map<String, Integer> rateMap = MimeTypeUtils.RATE.get(rate);
		Integer width = rateMap.get("width");
		Integer height = rateMap.get("height");

		commend.add("scale="+width+":"+height);   //9:16

        commend.add("-vcodec");
        commend.add("h263");  //
        commend.add("-ab");		//新增4条
        commend.add("128");      //高品质:128 低品质:64
        commend.add("-acodec");
        commend.add("mp3");      //音频编码器：原libmp3lame
        commend.add("-ac");
        commend.add("2");       //原1
        commend.add("-ar");
        commend.add("22050");   //音频采样率22.05kHz
        commend.add("-r");
        commend.add("30");  //高品质:30 低品质:15
        commend.add("-c:v");
        commend.add("libx264");	//视频编码器：视频是h.264编码格式
        commend.add("-strict");
        commend.add("-2");
        commend.add(outPath);  // //转码后的名称，是指定后缀的视频

        //打印命令--zoutao
        StringBuffer test = new StringBuffer();
        for (int i = 0; i < commend.size(); i++) {
            test.append(commend.get(i) + " ");
        }
        System.out.println("ffmpeg输入的命令:"+test);

        try {
            //多线程处理加快速度-解决rmvb数据丢失builder名称要相同
            ProcessBuilder builder = new ProcessBuilder();
            builder.command(commend);
            Process p = builder.start();   //多线程处理加快速度-解决数据丢失

			doWaitFor(p);

            p.waitFor();//进程等待机制，必须要有，否则不生成mp4！！！

            p.destroy();
            System.out.println("生成mp4视频为:"+outPath);
            return true;
        }
        catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

	public static int doWaitFor(Process p) {
		InputStream in = null;
		InputStream err = null;
		int exitValue = -1;
		try {
			in = p.getInputStream();
			err = p.getErrorStream();
			boolean finished = false;

			while (!finished) {
				try {
					while (in.available() > 0) {
						in.read();
					}
					while (err.available() > 0) {
						err.read();
					}

					exitValue = p.exitValue();
					finished = true;

				} catch (IllegalThreadStateException e) {
					Thread.sleep(500);
				}
			}
		} catch (Exception e) {
			log.error("doWaitFor();: unexpected exception - " + e.getMessage());
		} finally {
			try {
				if (in != null) {
					in.close();
				}

			} catch (IOException e) {
				log.info(e.getMessage());
			}
			if (err != null) {
				try {
					err.close();
				} catch (IOException e) {
					log.info(e.getMessage());
				}
			}
		}
		return exitValue;
	}

}
